#pragma once

#include <iostream>
#include <string>
#include <vector>
#include<algorithm>
#include <cassert>
#include <unordered_map>
#include <fstream>

#include "../comm/log.hpp"

using namespace ns_log;

namespace ns_model
{
    using namespace std;
    struct Question
    {
    public:
        string title;  // 题目标题
        string number; // 题目编号
        string desc;   // 题目描述
        int cpu_lim;   // 题目时间限制（s）
        int mem_lim;   // 题目空间限制（kb）
        string star;   // 题目难度
        string header; // 题目中可以编写代码
        string tail;   // 题目的测试用例
    };

    const std::string questins_list = "./questions/questions.list";
    const std::string questins_path = "./questions/";
    
    class Model
    {
    public:
        Model()
        {
            assert(LoadQuestion(questins_list));
        }
        // 加载配置文件:quest_nums.list+题号
        bool LoadQuestion(const string &question_list)
        {
            ifstream in(questins_list);
            if (!in.is_open())
            {
                LOG(FATAL) << "用户打开题库文件失败！" << "\n";
                return false;
            }
            string line;
            while (getline(in, line))
            {
                vector<string> tokens;
                // 分割字符串将不同部分置于tokens中
                StringUtil::SpiltString(line, &tokens, " ");
                // eg 1 判断回文 简单 1 30000
                if (tokens.size() == 0)
                {
                    LOG(WARNING) << "用户获取题目信息失败！" << "\n";
                    continue;
                }
                Question q;
                q.number = tokens[0];
                q.title = tokens[1];
                q.star = tokens[2];
                q.cpu_lim = atoi(tokens[3].c_str());
                q.mem_lim = atoi(tokens[4].c_str());

                string path = questins_path;
                path += q.number;
                path += "/";

                FileUtil::ReadFile(path + "desc.txt", &(q.desc), true);
                FileUtil::ReadFile(path + "header.cpp", &(q.header), true);
                FileUtil::ReadFile(path + "tail.cpp", &(q.tail), true);

                questions.insert({q.number, q});
            }
            in.close();
            LOG(INFO) << "用户获取题库文件成功！" << "\n";
            return true;
        }
        // 获取题目信息
        bool GetAllQuestions(vector<Question> *out)
        {
            if (questions.size() == 0)
            {
                LOG(WARNING) << "用户获取题目列表失败" << "\n";
                return false;
            }
            for (auto &q : questions)
            {
                out->push_back(q.second);
            }
            return true;
        }
        bool GetOneQuest(string &quest_num, Question *out)
        {
            auto iter = questions.find(quest_num);
            if (iter == questions.end())
            {
                LOG(WARNING) << "用户获取题目失败,题目为：" << quest_num << "\n";
                return false;
            }
            *out = iter->second;
            return true;
        }
        ~Model()
        {
        }

    private:
        unordered_map<string, Question> questions; // 题目编号：题目细节
    };
}